/******************************************************************************
 *  _____     _____
 *  \  __\    \  __\
 *   \ \_\\    \ \_\\
 *    \  __\SS  \  __\roject
 *     \_\       \_\
 *
 * Mateusz Maciąg, Rafał Urbański
 * Komputerowe Systemy Sterowania
 *****************************************************************************/
 
#ifndef UTILS_H
#define UTILS_H

#include <vector>
#include <string>

namespace RafMat
{

/**
    Klasa wykorzystująca wzorzec projektowy "Worek na śmieci".

    Klasa statyczna gromadzi różne drobne operacje, które w zasadzie
    można wykorzystać wszędzie, a zarazem nie wiadomo w jakiej klasie
    je umieścić.
*/
class Utils
{
public:
    /**
        Konwertuje łańcuch znakowy do wektora.

        Metoda statyczna zmienia łańcuch postaci "[ a0 a1 a2 ... an ]"
        na pojemnik std::vector<double>.

        \param [in] s Łańcuch wejściowy
        \param [out] succeed Flaga wskazująca na powodzenie konwersji.
        \return Wektor z elementami \c double wymienionymi w łańcuchu.
    */
    static std::vector<double> convertStrToVector(const std::string& s, bool& succeed);

    /**
        Usuwa wiodące i końcowe spacje.

        \param [in] Łańcuch wejściowy.
        \return Łańcuch po zmodyfikowaniu.
    */
    static std::string trimWhiteSpaces(const std::string& str);

    /**
        Sprawdza czy łańcuch spełnia reguły nazywania identyfikatorów.

        \param [in] Łańcuch wejściowy.
        \return Wartość \c true w przypadku dopasowania, \c false w przeciwnym razie.
    */
    static bool matchesIdentifier(const std::string& str);

    /**
        Sprawdza czy istnieje dany element w mapie.

        \param [in] pMap Mapa STL.
        \param [in] pKey Klucz, którego szukamy.
        \return True, jeśli element istnieje. False - w przeciwnym wypadku.
    */
    template <typename Map, typename Key>
    static bool mapContains(const Map& pMap, const Key& pKey)
    {
        return pMap.find(pKey) != pMap.end();
    }

    /** Sprawdza czy istnieje dany element w mapie.

        \tparam Map Kontener typu zgodny z std::map.
        \tparam Key Typ klucza.
        \param [in] pMap Mapa STL.
        \param [in] pKey Klucz, którego szukamy.
        \param [out] result Rezultat poszukiwań. True jeśli znaleziono, false w przeciwnym wypadku.
        \return Iterator do znalezionego elementu.
    */
    template <typename Map, typename Key>
    static typename Map::const_iterator mapContains(const Map& pMap, const Key& pKey, bool& result)
    {
        typename Map::const_iterator it = pMap.find(pKey);
        result = (it != pMap.end());
        return it;
    }

    /** Ogranicza zadaną wartość.
        Szablon funkcji zwraca wartość mieszczącą się w przedziale <min; max>.
        Jeśli wartość \c value przekracza ów przedział, zostanie zwrócona jedna
        z granic przedziału (w zależności od tego, z której strony przekroczono wartość).

        Wynik działania funkcji dla min > max należy uznać za nieokreślony i powinno się
        unikać takich sytuacji.

        \tparam Tp Typ wbudowany lub dowolny typ ze zdefiniowanymi operatorami '<', '>',
        oraz konstruktorem kopiującym.
        \param [in] value Wartość, którą chcemy ograniczyć.
        \param [in] min Ograniczenie dolne.
        \param [in] max Ograniczenie górne.
        \return Wartość z poddanym ograniczeniem.
    */
    template <typename Tp>
    static Tp limitValue(Tp value, Tp min, Tp max)
    {
        return (value > max) ? max : ((value < min) ? min : value);
    }

private:
    // Klasa statyczna
    Utils() {}
};

} // namespace RafMat

#endif // UTILS_H
